module V1
  module APIGuard
    extend ActiveSupport::Concern

    included do |base|
      use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request|
        request.access_token
      end
      helpers HelperMethods

      install_error_responders(base)
    end

    module HelperMethods
      def guard!
        token_string = get_token_string()
        raise MissingTokenError if token_string.blank?
        #@current_user = validate_token(token_string)
        @current_user = User.first
      end

      private
      def get_token_string
        request.env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN]
      end

      def validate_token token_string
        token = Rack::OAuth2::AccessToken::Bearer.new(access_token: token_string)
        raw_info = JSON.parse token.get('http://www.geekpark.net/api/v1/user').body
        if raw_info['uuid']
          begin
            user = User.find_or_create_by!(id: raw_info['uuid'])
            user.update(trim_params(raw_info))
          rescue ActiveRecord::RecordNotUnique
            user = User.find raw_info['uuid']
          end
          user
        else
          raise InvalidTokenError
        end
      end

      def trim_params(user_params)
        user_params['avatar'] = user_params['avatar']['url']
        u = ActionController::Parameters.new(user_params)
        u.slice('username', 'email', 'realname', 'mobile', 'company', 'position', 'avatar', 'bio', 'city', 'mygeekpark_open_id').permit!
      end
    end

    module ClassMethods
      private
      def install_error_responders(base)
        error_classes = [ MissingTokenError, InvalidTokenError]
        base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
      end

      def oauth2_bearer_token_error_handler
        Proc.new {|e|
          response = case e
            when MissingTokenError
              Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new

            when InvalidTokenError
              Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
                :invalid_token,
                "Bad Access Token.")
            end
          response.finish
        }
      end
    end

    class MissingTokenError < StandardError; end
    class InvalidTokenError < StandardError; end
  end
end

